package com.springboot.cloud.sysadmin.organization.rest;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.springboot.cloud.common.core.domain.AjaxResult;
import com.springboot.cloud.common.core.entity.vo.Result;
import com.springboot.cloud.common.core.utils.EncryptUtils;
import com.springboot.cloud.common.core.utils.StringUtils;
import com.springboot.cloud.common.core.utils.poi.ExcelUtil;
import com.springboot.cloud.sysadmin.organization.config.MyMetaObjectHandler;
import com.springboot.cloud.sysadmin.organization.config.Shuguoyiyou;
import com.springboot.cloud.sysadmin.organization.entity.form.*;
import com.springboot.cloud.sysadmin.organization.entity.param.UserQueryParam;
import com.springboot.cloud.sysadmin.organization.entity.po.User;
import com.springboot.cloud.sysadmin.organization.entity.vo.UserVo;
import com.springboot.cloud.sysadmin.organization.file.FileUploadUtils;
import com.springboot.cloud.sysadmin.organization.service.IUserService;
import com.springboot.cloud.sysadmin.organization.until.RedisUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * Created by ZengJian on 2021/2/3 0003 上午 9:22
 */
@Slf4j
@Api(tags = "用户")
@RestController
@RequestMapping("/user")

public class UserController {
    @Autowired
    private   IUserService userService;

    @Resource
    private RedisUtils redisUtils;

    private String tokenId = "TOKEN-USER-";

    @ApiOperation(value = "导出用户数据", notes = "导出数据")
    @PostMapping("/export")
    public AjaxResult export() {
        List<User> list = userService.listUser();
        log.debug("search with list:{}", list);
        ExcelUtil<User> util = new ExcelUtil<User>(User.class);
        return util.exportExcel(list, "用户数据导出");
    }

    @ApiOperation("导出用户数据")
    @GetMapping(value = "/download")
    public void download(HttpServletResponse response, UserQueryForm userQueryForm) throws IOException {
        userService.download(userService.listUser(), response);
    }

    @PostMapping("/excel/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        log.debug("updateSupport:", updateSupport);
        ExcelUtil<User> util = new ExcelUtil<User>(User.class);
        List<User> userList = util.importExcel(file.getInputStream());
        log.debug("userList:", userList);

        String username = getUsername();
        log.debug("username:", username);
        String message = userService.importUser(userList, updateSupport, username);
        return AjaxResult.success(message);
    }

    @GetMapping("/excel/importTemplate")
    public AjaxResult importTemplate() {
        ExcelUtil<User> util = new ExcelUtil<User>(User.class);
        return util.importTemplateExcel("用户数据");
    }


    @ApiOperation(value = "新增用户", notes = "新增一个用户")
    @PostMapping
    public Result add(@Valid @RequestBody UserForm userForm) {
        if (StrUtil.isNotBlank(userForm.getMobile()) && !Validator.isMobile(userForm.getMobile())) {
            return Result.error("请输入正确的手机号");
        }
        log.debug("userForm:{}", userForm);
        if (userService.add(userForm.toPo(User.class))) {
            return Result.success("新增用户成功");
        } else {
            return Result.error("该账号或手机号已被注册");
        }
    }

    @ApiOperation(value = "删除用户", notes = "根据url的id来指定删除对象，逻辑删除")
    @DeleteMapping
    public Result deleteByUserIds(@Valid @RequestBody Set<String> ids) {
        if (StringUtils.isEmpty(ids)) {
            return Result.error("没选中要删除的用户");
        } else if (userService.delete(ids)) {
            return Result.success("删除用户成功");
        }
        return Result.error("没选中要删除的用户");

    }

    @ApiOperation(value = "修改用户", notes = "修改指定用户信息")
    @PutMapping(value = "/{id}")
    public Result update(@PathVariable String id, @Valid @RequestBody UserForm userForm) {
        if (StrUtil.isNotBlank(userForm.getMobile()) && Validator.isMobile(userForm.getMobile())) {
            return Result.error("请输入正确的手机号");
        }
        if (StrUtil.isBlank(id)) {
            return Result.error("查找不到对应值");
        }
        log.debug("get user id:{}", id);
        User user = userForm.toPo(User.class);
        user.setId(id);
        if (userService.update(user)) {
            return Result.success("修改用户信息成功");
        }
        return Result.error("修改用户信息失败");

    }

    @ApiOperation(value = "修改用户", notes = "修改指定用户信息")
    @PutMapping(value = "/basic/{id}")
    public Result updateBasic(@PathVariable String id, @Valid @RequestBody UserUpdateBasicForm userUpdateBasicForm) {
        if (StrUtil.isBlank(id)) {
            return Result.error("用户的id不可为空");
        }
        User user = userUpdateBasicForm.toPo(User.class);
        user.setId(id);
        if (userService.updateBasic(user)) {
            return Result.success("修改用户信息成功");
        }
        return Result.success("修改用户信息失败");
    }

    @ApiOperation(value = "修改自己密码", notes = "修改密码")
    @PutMapping(value = "/updatePwd")
    public Result updateUserPwd(String oldPassword, String newPassword) {
        String username = getUsername();
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (!passwordEncoder.matches(oldPassword, userService.getByUniqueId(username).getPassword())) {
            return Result.error("修改密码失败，旧密码错误"); // 修改密码失败，旧密码错误
        } else if (passwordEncoder.matches(newPassword, userService.getByUniqueId(username).getPassword())) {
            return Result.error("新密码不能与旧密码相同");  // 新密码不能与旧密码相同
        }
        User user = new User();
        user.setUsername(username);
        user.setPassword(newPassword);
        if (userService.updateUserPwd(user)) {
            return Result.success("重置密码成功");
        }
        return Result.error("重置密码失败");
    }

    @ApiOperation(value = "重置密码", notes = "重置密码")
    @PutMapping(value = "/resetPwd")
    public Result resetPwd(@Valid @RequestBody ResetUserPwdForm resetUserPwdForm) {

        log.debug("user:", resetUserPwdForm.getId());
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (passwordEncoder.matches(resetUserPwdForm.getPassword(), userService.getByUserId(resetUserPwdForm.getId()).getPassword())) {
            return Result.error("新密码不能与旧密码相同");  // 新密码不能与旧密码相同
        }
        User user = userService.getByUserId(resetUserPwdForm.getId());
//        user.setId(resetUserPwdForm.getId());
        user.setPassword(resetUserPwdForm.getPassword());
        if (userService.updateUserPwd(user)) {
            return Result.success("重置密码成功");
        }
        return Result.error("重置密码失败");
    }


    @ApiOperation(value = "忘记密码", notes = "忘记密码")
    @PutMapping(value = "/forgetPwd")
    public Result forgetPwd(@Valid @RequestBody ResetMobilePwdForm resetMobilePwdForm) {
//        String secret = "zswedxcfrtgvbhybhujng";
//        EncryptUtils.getEncrypt(redisUtils.get(tokenId+resetMobilePwdForm.getMobile()));
        //首先比对验证码是否失效
        String redisauthcode = redisUtils.get(tokenId + resetMobilePwdForm.getMobile()); //传入tonkenId返回redis中的value
        if (StrUtil.isBlank(redisauthcode)) {
            //如果未取到则过期验证码已失效
            return Result.error("验证码已过期，重置密码失败");
        } else if (!"".equals(redisauthcode) && !resetMobilePwdForm.getTime().equals(EncryptUtils.getEncrypt(redisauthcode))) {
            //验证码错误
            return Result.error("验证码错误，重置密码失败");
        }
//        if(!resetMobilePwdForm.getTime().equals(EncryptUtils.getEncrypt(redisUtils.get(tokenId+resetMobilePwdForm.getMobile())))){
//            return Result.error("重置密码失败");
//        }
        log.debug("mobile:", resetMobilePwdForm.getMobile());
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (passwordEncoder.matches(resetMobilePwdForm.getPassword(), userService.getByUniqueId(resetMobilePwdForm.getMobile()).getPassword())) {
            return Result.error("新密码不能与旧密码相同");  // 新密码不能与旧密码相同
        }
        User user = userService.getByUserId(resetMobilePwdForm.getMobile());
//        user.setId(resetUserPwdForm.getId());
        user.setPassword(resetMobilePwdForm.getPassword());
        if (userService.updateUserPwd(user)) {
            return Result.success("重置密码成功");
        }
        return Result.error("重置密码失败");
    }

    /**
     * 状态修改
     */
    @ApiOperation(value = "修改用户状态", notes = "用户id和状态修改用户状态")
    @PutMapping("/changeEnabled")
    public Result changeEnabled(@Valid @RequestBody UserUpdateEnabled userUpdateEnabled) {
        User user = userUpdateEnabled.toPo(User.class);
        if (userService.updateEnabled(user)) {
            return Result.success("修改用户状态成功");
        }
        return Result.error("更新用户状态失败，请检查有无该用户");
    }

    @GetMapping(value = "/profile")
    public Result Username() {
        String uniqueId = getUsername();
        return query(uniqueId);
    }

    @GetMapping(value = "/profiles")
    public String Usernames() {
        String name = getUsername();
        return name;
    }

    @ApiOperation(value = "获取用户", notes = "获取指定用户信息")
    @ApiImplicitParam(paramType = "path", name = "id", value = "用户ID", required = true, dataType = "String")
    @GetMapping(value = "/{id}")
    public Result get(@PathVariable String id) {
        if (StrUtil.isBlank(id)) {
            return Result.error("id不可为空");
        }
        log.debug("get with id:{}", id);
        if (userService.getUser(id)) {
            return Result.success(userService.get(id));
        }
        return Result.error("查找失败");

    }

    @ApiOperation(value = "获取用户", notes = "获取指定用户信息")
    @ApiImplicitParam(paramType = "path", name = "id", value = "用户ID", required = true, dataType = "String")
    @GetMapping(value = "/getUser/{id}")
    public UserVo getUser(@PathVariable String id) {

        log.debug("get with id:{}", id);
        return userService.get(id);
    }

    @ApiOperation(value = "获取用户", notes = "根据用户唯一标识（username or mobile）获取用户信息")
    @ApiImplicitParam(paramType = "query", name = "uniqueId", value = "用户唯一标识", required = true, dataType = "String")
    @GetMapping
    public Result query(@RequestParam String uniqueId) {
        if (StrUtil.isBlank(uniqueId)) {
            return Result.error("值不可为空");
        }
        return Result.success(userService.getByUniqueId(uniqueId));

    }

    @ApiOperation(value = "获取用户", notes = "根据用户唯一标识（username or mobile）获取用户信息")
    @ApiImplicitParam(paramType = "query", name = "uniqueId", value = "用户唯一标识", required = true, dataType = "String")
    @GetMapping(value = "/getAllByUniqueId")
    public Result getAllByUniqueId() {
        String uniqueId = getUsername();
        if (StrUtil.isBlank(uniqueId)) {
            return Result.error("值不可为空");
        }
        return Result.success(userService.getAllByUniqueId(uniqueId));

    }


    @GetMapping(value = "/getUserByUsername")
    public User getUserByUsername(@RequestParam String uniqueId) {
        return userService.getByUniqueId(uniqueId);
    }

//    @GetMapping
//    public Result<User> getUserByUniqueId(@RequestParam String uniqueId) {
//        return Result.success(userService.getByUniqueId(uniqueId));
//    }

    @ApiOperation(value = "搜索用户", notes = "根据条件查询用户信息")
    @PostMapping(value = "/conditions")
    public Result search(@Valid @RequestBody UserQueryForm userQueryForm) {
        if (userQueryForm.getCreatedTime() != null && !userQueryForm.getCreatedTime().isEmpty()) {
            userQueryForm.setCreatedTimeStart(userQueryForm.getCreatedTime().get(0));
            userQueryForm.setCreatedTimeEnd(userQueryForm.getCreatedTime().get(1));
        }
        log.debug("search with userQueryForm:{}", userQueryForm);
        return Result.success(userService.query(userQueryForm.getPage(), userQueryForm.toParam(UserQueryParam.class)));
    }

    @PostMapping(value = "/searchByNickname")
    public IPage<UserVo> searchByNickname(@Valid @RequestBody UserQueryForm userQueryForm) {
        log.debug("search with userQueryForm:{}", userQueryForm);
        IPage<UserVo> iPage = userService.query(userQueryForm.getPage(), userQueryForm.toParam(UserQueryParam.class));
        return iPage;
    }

    /**
     * 头像上传
     */
    @ApiOperation(value = "用户头像", notes = "上传用户头像")
//    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
    @PostMapping("/avatar")
    public Result avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException {
        User user = userService.getByUniqueId(getUsername());
        if (!file.isEmpty()) {
            String avatar = FileUploadUtils.upload(Shuguoyiyou.getAvatarPath(), file);
            user.setAvatar(avatar);
            return Result.success(userService.updateUserAvatar(user));
        }
        return Result.error("上传图片异常，请联系管理员");
    }

    public String getUsername() {
        MyMetaObjectHandler myMetaObjectHandler = new MyMetaObjectHandler();
        return myMetaObjectHandler.getCurrentUsername();
    }

    @ApiOperation(value = "添加公众号openId", notes = "添加公众号openId")
    @PutMapping(value = "/updateOpenId")
    public Result updateOpenId(@Valid @RequestBody UserOpenIdForm userOpenIdForm) {
        if (userService.updateOpenId(userOpenIdForm.getUsername(), userOpenIdForm.getOpenId())) {
            return Result.success("修改用户信息成功");
        }
        return Result.error("修改用户信息失败");
    }

    @ApiOperation(value = "根据公众号openId获取用户信息", notes = "根据公众号openId获取用户信息")
    @GetMapping(value = "/getUserByOpenId")
    public Result<User> getUserByOpenId(@RequestParam String openId) {
        return Result.success(userService.getUserByOpenId(openId));
    }
}
